/*
 * UMLSynch plugin for Eclipse
 * http://umlsynch.googlecode.com
 *
 * Copyright 2008-2010, Evgeny Alexeyev
 * Licensed under the EPL - v1.0
 * http://www.eclipse.org/legal/epl-v10.html
 *
 */

package com.googlecode.umlsynch.eclipse.socket;



import java.io.*;
import java.net.*;


import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.ui.IViewPart;
import org.eclipse.ui.internal.WorkbenchPlugin;
import org.eclipse.ui.views.IViewDescriptor;
import org.eclipse.ui.views.IViewRegistry;

import org.eclipse.ui.console.ConsolePlugin;
import org.eclipse.ui.console.IConsole;
import org.eclipse.ui.console.IConsoleManager;
import org.eclipse.ui.console.MessageConsole;
import org.eclipse.ui.console.MessageConsoleStream;

import org.eclipse.cdt.core.CCorePlugin;

import com.googlecode.umlsynch.eclipse.astutils.ASTUtils;




public class EclipseServerSocket {
    
	ServerSocket server;
    int num;
    boolean flag;
    // 64k buffer for input stream  
    byte buf[] = new byte[64*1024];

    String eclipsePluginId = "Eclipse plugin for VP SDE v1.0";
	String vpsdePluginId = "VP SDE plugin for Eclipse v1.0";
	//MessageConsole myConsole;
	//MessageConsoleStream debugOut;
	
	public EclipseServerSocket() {
	    
	}
	/*
    private MessageConsole findConsole(String name) 
    {
	    ConsolePlugin plugin = ConsolePlugin.getDefault();
	    IConsoleManager conMan = plugin.getConsoleManager();
	    	    
	    IConsole[] existing = conMan.getConsoles();
	    for (int i = 0; i < existing.length; i++)
	    {
	    	System.out.println(existing[i].getName());
	         if (name.equals(existing[i].getName()))
	            return (MessageConsole) existing[i];
	    //no console found, so create a new one
	    }
	    MessageConsole myConsole = new MessageConsole(name, null);
	    conMan.addConsoles(new IConsole[]{myConsole});
	    
	    return myConsole;
	}
*/
    public void initializeServer() throws CoreException
    {
        
    	//myConsole = findConsole("EclipsePluginForVPSDEPlugin");
        //debugOut = myConsole.newMessageStream();
        System.out.println("Test Messasge");
        /*
    	IViewRegistry vr = WorkbenchPlugin.getDefault().getViewRegistry();
    	IViewDescriptor[] vds = vr.getViews();
    	IViewDescriptor console = null;
	    for (int i = 0; i < vds.length; i++)
	    {
	    	if (vds[i].getId().equals("org.eclipse.ui.console.ConsoleView"))
	    	{
	    		System.out.println(vds[i].getLabel());
	    		System.out.println(vds[i].getDescription());
	    		console = vds[i];
	    	}
	    }
    	*/
	    
	    
	    
        System.out.println("Init Server");
        
    	Job operation = new Job("SocketPlugin") 
        {
    	      protected IStatus run(IProgressMonitor monitor)  
    	      {
    	      	try {
    				server = new ServerSocket(3128, 0, InetAddress.getByName("localhost"));
    			} catch (UnknownHostException e1) {
    				System.out.println("Unknown host");
    				return Status.OK_STATUS;
    			} catch (IOException e1) {
    				System.out.println("IO Exception");
    				return Status.OK_STATUS;
    			}
    	    	  try
    	          {
    	        	  // accept client socket
    	    		  System.out.println("accept client");    	        	  
        	    	  Socket s = server.accept();
        	    	  System.out.println("client accepted");
        	    	  // check the client 
        		      StartReadingLoop(s);
        		      System.out.println("handshaked");
    	              // close access for client socket
    	              s.close();
        		      // close server socket
        		      server.close();
    	          }
    	    	  catch (IOException e1)
    	    	  {
    	    		  System.out.println("IOException occured");
    	    		// TODO: close client and server socket    	    		  
    	    	  }
    	          catch(Exception e) 
    	          {
    	    		  System.out.println("Exception occured");
    	              // TODO: parse output correctly
    	          }
				return Status.OK_STATUS;
    	      }
        };
        // run client-server communication 
          operation.setPriority(Job.INTERACTIVE);
          operation.schedule();
    }	
    
    private String ProcessData(String inputData)
    {
    	String output = "unknown command";
    	
    	String[] inputDataSplit = inputData.split(":");
    	
    	String cmd = inputDataSplit[0];
    	
    	int argsNum = inputDataSplit.length;
 
    	ASTUtils au = ASTUtils.instance();
    	
    	
    	if (cmd.equals(vpsdePluginId))
    	{
    		output = eclipsePluginId;
    	} 
    	else if (cmd.equals("close session"))
    	{
    		flag = false;
    		output = inputData;
    	}
    	else if (cmd.equals("getClassBases"))
    	{
    		output = "returnClassBases";
    		if (argsNum == 3)
    		{
    		//	output= output.concat(
    			 //   au.getBaseClass(
    			   // 	au.GetProject(inputDataSplit[1]), inputDataSplit[2]));
    		}
    	}
    	else if (cmd.equals("getClassSubClasses"))
    	{
    		output = "returnClassSubClasses";
    		if (argsNum == 3)
    		{
    		//	output= output.concat(
    			    //au.getSubClasses(
    			    	//au.GetProject(inputDataSplit[1]), inputDataSplit[2]));
    		}
    	}
    	else if (cmd.equals("getClassAllDeclaredMethods"))
    	{
    		output = "returnClassAllDeclaredMethods";
    		if (argsNum == 3)
    		{
    		//	output= output.concat(
    		//	    au.getClassMethods(
    			//    	au.GetProject(inputDataSplit[1]), inputDataSplit[2]));
    		}
    	}
    	else if (cmd.equals("getClassDeclaredMethods"))
    	{
    		output = "returnClassDeclaredMethods";
    		if (argsNum == 3)
    		{
    		//	output= output.concat(
    		//	    au.getClassDeclaredMethods(
    			//    	au.GetProject(inputDataSplit[1]), inputDataSplit[2]));
    		}
    	}
    	else if (cmd.equals("getClassAllFields"))
    	{
    		output = "returnClassAllFields";
    		if (argsNum == 3)
    		{
    			//output= output.concat(
    	//		    au.getClassAllField(
    		//	    	au.GetProject(inputDataSplit[1]), inputDataSplit[2]));
    		}
    	}
    	else if (cmd.equals("getClassFields"))
    	{
    		output = "returnClassFields";
    		if (argsNum == 3)
    		{
    	//		output= output.concat(
    		//	    au.getClassDeclaredField(
    			//    	au.GetProject(inputDataSplit[1]), inputDataSplit[2]));
    		}
    	}
    	else if (cmd.equals("getClassFriend"))
    	{
    		output = "returnClassFriend";
    	}

    	return output;
    }
    
    private void StartReadingLoop(Socket clientSocket) throws IOException
    {
        // get io streams
        InputStream is = clientSocket.getInputStream();
        OutputStream os = clientSocket.getOutputStream();

        // fill 64k buffer 
        int r =0 ;
        flag = true;
        
        do 
        {
        	if (is.available() > 0)
        	{
        		r  = is.read(buf);
                // convert data to string for parsing
                String data = new String(buf, 0, r);
                String outputData = ProcessData(data);
                os.write(outputData.getBytes());                
        	}
        }while (flag);
    }
    
    public void createNewDiagram(String diagramType, String diagramName)
    {
    	// TODO: send request to client for new diagram
    }
    
    public void showDiagramOverview(String elementName)
    {
    	// TODO: make an overview of diagrams, which contain current eleemnt
    }
    
    public void parseInputRequest(String inputRequest)
    {
    	// TODO: parse input data from socket 
    	//       add project="projectName" file="fileName.*"
    	//       get Class/Interface/...="NameTemplate" action=""
    	//       open interface/class/...="Template" action=declaration/implementation
    	//       ..... extensible interface
    }
    
    private void addElementToProject(String projectName, String elementName)
    {
    	// TODO: add File or new directory into the current project  
    }

    private void getElementByName(String elementInstanceType, String elementNameTemplate, String elementActionType)
    {
    	// TODO: output the list of interfaces/classes/etc...
    	//       Find object by name and performe some actions:
    	//       -- access to methods
    	//       -- access to members
    	//       -- get subclasses 
    	//       -- get superclass's
    	//       -- get x-references
    	//       -- and any extensions welcome
    }
    private void openElementInstace(String elementInstanceType, String elementName, String openFlag)
    {
    	// TODO: open file/class/interface/variable ...  in the workbench 
    	//       openFlag - "declaration" or "definition" [and probably "new" is required too]
    }
}
